home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianVisArrows.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  26KB  |  902 lines

  1. /*ScianVisArrows.c
  2.   June 14, 1991
  3.   Eric Pepke
  4.   Routines for arrows visualization object
  5.  
  6.   The arrow object takes a vector field defined over a data form with
  7.   any number of topological dimensions, 2 or 3 spatial dimensions, and 2 
  8.   or 3 components and draws arrows at each point.  The arrow visualization
  9.   object works for regular data forms, curvilinear data forms, and
  10.   nonstructured data forms.
  11.  
  12. */
  13.  
  14. #include "Scian.h"
  15. #include "ScianTypes.h"
  16. #include "ScianArrays.h"
  17. #include "ScianWindows.h"
  18. #include "ScianTextBoxes.h"
  19. #include "ScianObjWindows.h"
  20. #include "ScianIcons.h"
  21. #include "ScianColors.h"
  22. #include "ScianControls.h"
  23. #include "ScianLists.h"
  24. #include "ScianSpaces.h"
  25. #include "ScianSliders.h"
  26. #include "ScianIDs.h"
  27. #include "ScianDatasets.h"
  28. #include "ScianErrors.h"
  29. #include "ScianVisObjects.h"
  30. #include "ScianVisWindows.h"
  31. #include "ScianVisArrows.h"
  32. #include "ScianStyle.h"
  33. #include "ScianPictures.h"
  34. #include "ScianTitleBoxes.h"
  35. #include "ScianButtons.h"
  36. #include "ScianMethods.h"
  37. #include "ScianTemplates.h"
  38. #include "ScianTemplateHelper.h"
  39. #include "ScianSymbols.h"
  40.  
  41. ObjPtr arrowsClass;
  42.  
  43. static ObjPtr ArrowsInit(object)
  44. ObjPtr object;
  45. /*Initializes an arrows object*/
  46. {
  47.     real bounds[6];
  48.  
  49.     if (GetBounds(object, bounds))
  50.     {
  51.     real size;
  52.     size = bounds[1] - bounds[0];
  53.     size = MAX(size, bounds[3] - bounds[2]);
  54.     size = MAX(size, bounds[5] - bounds[4]);
  55.  
  56.     SetVar(object, HEADWIDTH, NewReal(size * 0.01));
  57.     SetVar(object, SHAFTWIDTH, NewReal(size * 0.005));
  58.     SetVar(object, HEADLENGTH, NewReal(size * 0.03));
  59.  
  60.     /****UPDATE*** determine heuristically from dataset*/
  61.     SetVar(object, VECTORFACTOR, NewReal(1.0));
  62.     }
  63.     else
  64.     {
  65.     SetVar(object, HEADWIDTH, NewReal(0.01));
  66.     SetVar(object, SHAFTWIDTH, NewReal(0.005));
  67.     SetVar(object, HEADLENGTH, NewReal(0.03));
  68.  
  69.     SetVar(object, VECTORFACTOR, NewReal(0.5));
  70.     }
  71.     return ObjTrue;
  72. }
  73.  
  74. static ObjPtr SetArrowsMainDataset(visObj, dataSet)
  75. ObjPtr visObj, dataSet;
  76. /*Sets the main data set of visObj to dataSet*/
  77. {
  78.     SetVar(visObj, MAINDATASET, dataSet);
  79.     return ObjTrue;
  80. }
  81.  
  82. static ObjPtr MakeArrowsColored(visObject)
  83. ObjPtr visObject;
  84. /*Makes the arrows colored*/
  85. {
  86.     SetVar(visObject, PICCOLORED, ObjTrue);
  87.     if (GetPredicate(visObject, COLORS))
  88.     {
  89.     ObjPtr colorField;
  90.     real brightness;
  91.     ObjPtr var;
  92.     ObjPtr surface;
  93.     ObjPtr palette;
  94.  
  95.     /*Get the color field and its form*/
  96.     colorField = GetVar(visObject, COLOROBJ);
  97.     if (!colorField) return ObjFalse;
  98.  
  99.     /*Get the color palette*/
  100.     MakeVar(colorField, CPALETTE);
  101.     palette = GetPaletteVar("MakeArrowsColored", colorField, CPALETTE);
  102.     if (!palette)
  103.     {
  104.         return ObjFalse;
  105.     }
  106.     SetPalette(palette);
  107.  
  108.     /*Get the surface to color*/
  109.     surface = GetPictureVar("MakeArrowsColored", visObject, SURFACE);
  110.     if (!surface) return ObjFalse;
  111.  
  112.     /*Have to make it colored by the object*/
  113.     ColorPictureByObject(surface, colorField, GetPredicate(visObject, INTERPCOLORS));
  114.     }
  115.     return ObjTrue;
  116. }
  117.  
  118. static ObjPtr MakeArrowsSurface(visObject)
  119. ObjPtr visObject;
  120. /*Makes the surface in a arrows object.  Also colors it.*/
  121. {
  122.     ObjPtr dataset;        /*The dataset the vis object represents*/
  123.     long datasetFlags;        /*Flags of the dataset*/
  124.     ObjPtr var;            /*Random variable*/
  125.     ObjPtr picture;        /*The picture to be made*/
  126.     real shaftWidth, headWidth, headLength, vecFactor;
  127.     int nSubdivisions;        /*# of subdivisions*/
  128.     int arrowStyle;        /*Style of arrow*/
  129.     int curCapEnds;        /*Whether or not to cap ends*/
  130.  
  131.     dataset = GetObjectVar("MakeArrowsSurface", visObject, MAINDATASET);
  132.     if (!dataset)
  133.     {
  134.     return ObjFalse;
  135.     }
  136.  
  137.     datasetFlags = GetDatasetInfo(dataset);
  138.  
  139.     if (0 == datasetFlags & DS_HASFORM)
  140.     {
  141.     ReportError("MakeArrowsSurface", "No data form");
  142.     return ObjFalse;
  143.     }
  144.  
  145.     /*Make the new picture*/
  146.     picture = NewPicture();
  147.     if (!picture) return ObjFalse;
  148.  
  149.     var = GetRealVar("MakeArrowsSurface", visObject, SHAFTWIDTH);
  150.     if (!var)
  151.     {
  152.     return ObjFalse;
  153.     }
  154.     shaftWidth = GetReal(var);
  155.  
  156.     var = GetRealVar("MakeArrowsSurface", visObject, HEADWIDTH);
  157.     if (!var)
  158.     {
  159.     return ObjFalse;
  160.     }
  161.     headWidth = GetReal(var);
  162.  
  163.     var = GetRealVar("MakeArrowsSurface", visObject, HEADLENGTH);
  164.     if (!var)
  165.     {
  166.     return ObjFalse;
  167.     }
  168.     headLength = GetReal(var);
  169.  
  170.     var = GetRealVar("MakeArrowsSurface", visObject, VECTORFACTOR);
  171.     if (!var)
  172.     {
  173.     return ObjFalse;
  174.     }
  175.     vecFactor = GetReal(var);
  176.  
  177.     {
  178.     int nTraversalDims;
  179.     long *indices;
  180.     long *traversalDims;
  181.     int whichDim;
  182.     int nFormComponents, nDataComponents;
  183.  
  184.     /*Get some parameters*/
  185.     var = GetIntVar("MakeArrowsSurface", visObject, FRUSTUMSUBDIV);
  186.     if (var)
  187.     {
  188.         nSubdivisions = GetInt(var);
  189.     }
  190.     else
  191.     {
  192.         nSubdivisions = 3;
  193.     }
  194.     curCapEnds = GetPredicate(visObject, CAPENDSP);
  195.     var = GetVar(visObject, STYLE);
  196.     if (var)
  197.     {
  198.         arrowStyle = GetInt(var);
  199.     }
  200.     else
  201.     {
  202.         arrowStyle = 0;
  203.     }
  204.  
  205.     /*Register the dataset and its dataform*/
  206.     if (!SetCurField(FIELD1, dataset))
  207.     {
  208.         return ObjFalse;
  209.     }
  210.     if (!SetCurForm(FORMFIELD, dataset))
  211.     {
  212.         return ObjFalse;
  213.     }
  214.  
  215.     /*Get the number of components*/
  216.     nFormComponents = GetNComponents(FORMFIELD);
  217.     nDataComponents = GetNComponents(FIELD1);
  218.     
  219.     /*Get the information on traversing the dataset*/
  220.     nTraversalDims = CountTraversalDims(FORMFIELD);
  221.     if (nTraversalDims)
  222.     {
  223.         traversalDims = (long *) Alloc(sizeof(long) * nTraversalDims);
  224.         indices = (long *) Alloc(sizeof(long) * nTraversalDims);
  225.     }
  226.     else
  227.     {
  228.         indices = (long *) Alloc(sizeof(long));
  229.     }
  230.     GetTraversalDims(FORMFIELD, traversalDims);
  231.  
  232.     /*Zero the index*/
  233.     for (whichDim = 0; whichDim < nTraversalDims; ++whichDim)
  234.     {
  235.         indices[whichDim] = 0;
  236.     }
  237.  
  238.     do
  239.     {
  240.         real x1, y1, z1, vx, vy, vz, len, nx, ny, nz;
  241.  
  242.         /*Get the beginning*/
  243.         x1 = SelectFieldComponent(FORMFIELD, 0, indices);
  244.         y1 = SelectFieldComponent(FORMFIELD, 1, indices);
  245.         if (nFormComponents < 3)
  246.         {
  247.         z1 = 0.0;
  248.         }
  249.         else
  250.         {
  251.         z1 = SelectFieldComponent(FORMFIELD, 2, indices);
  252.         }
  253.  
  254.         /*Do nothing for missing data*/
  255.         if (x1 == missingData ||
  256.         y1 == missingData ||
  257.         z1 == missingData)
  258.         {
  259.         goto nextOne;
  260.         }
  261.  
  262.         /*Get the vector*/
  263.         vx = SelectFieldComponent(FIELD1, 0, indices);
  264.         vy = SelectFieldComponent(FIELD1, 1, indices);
  265.         if (nDataComponents < 3)
  266.         {
  267.         vz = 0.0;
  268.         }
  269.         else
  270.         {
  271.         vz = SelectFieldComponent(FIELD1, 2, indices);
  272.         }
  273.  
  274.         /*Do nothing for missing data*/
  275.         if (vx == missingData ||
  276.         vy == missingData ||
  277.         vz == missingData)
  278.         {
  279.         goto nextOne;
  280.         }
  281.  
  282.         /*Multiply by vector factor*/
  283.         vx *= vecFactor;
  284.         vy *= vecFactor;
  285.         vz *= vecFactor;
  286.  
  287.         /*Get the length*/
  288.         len = sqrt(vx * vx + vy * vy + vz * vz);
  289.  
  290.         /*And the normalized vector*/
  291.         nx = vx / len;
  292.         ny = vy / len;
  293.         nz = vz / len;
  294.  
  295.         switch(arrowStyle)
  296.         {
  297.         case AS_LINE:
  298.         {
  299.             Vertex vertices[2];
  300.             vertices[0] . normal[0] = 0.0;
  301.             vertices[0] . normal[1] = 0.0;
  302.             vertices[0] . normal[2] = 1.0;
  303.             vertices[0] . position[0] = x1;
  304.             vertices[0] . position[1] = y1;
  305.             vertices[0] . position[2] = z1;
  306.             vertices[0] . colorIndex = 0;
  307.  
  308.             vertices[1] . normal[0] = 0.0;
  309.             vertices[1] . normal[1] = 0.0;
  310.             vertices[1] . normal[2] = 1.0;
  311.             vertices[1] . position[0] = x1 + vx;
  312.             vertices[1] . position[1] = y1 + vy;
  313.             vertices[1] . position[2] = z1 + vz;
  314.             vertices[1] . colorIndex = 0;
  315.  
  316.             AppendPolylineToPicture(picture, 1, 0, 2, vertices);
  317.         }
  318.         break;
  319.         case AS_FLAT:
  320.         {
  321.             int k;
  322.             float r[3];        /*Radial unit vector*/
  323.             float n[3];        /*Normal unit vector*/
  324.             float a[3];        /*Axial unit vector*/
  325.             double length, nf;
  326.  
  327.             a[0] = vx;
  328.             a[1] = vy;
  329.             a[2] = vz;
  330.  
  331.             length = sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
  332.             if (length <= 0.0)
  333.             {
  334.             /*Zero length vector, do nothing*/
  335.             break;
  336.             }
  337.  
  338.             nf = 1.0 / length;
  339.             a[0] *= nf; a[1] *= nf; a[2] *= nf;
  340.  
  341.             /*See if it's nearly colinear with k*/
  342.             if (ABS(a[2]) > 0.8)
  343.             {
  344.             /*It is, so cross by j to get first r*/
  345.             r[0] = -a[2];
  346.             r[1] = 0.0;
  347.             r[2] = a[0];
  348.             }
  349.             else
  350.             {
  351.             /*It isn't, so cross by k to get first r*/
  352.             r[0] = -a[1];
  353.             r[1] = a[0];
  354.             r[2] = 0;
  355.             }
  356.  
  357.             NORMALIZE(r);
  358.  
  359.             /*Cross a with first radial unit to get orthogonal unit*/
  360.             CROSS(a, r, n);
  361.  
  362.             /*Fill in the vertices and draw*/
  363.  
  364.             if (headLength >= len)
  365.             {
  366.             /*There's no shaft*/
  367.             Vertex vertices[3];
  368.  
  369.             /*Set up vertices*/
  370.             for (k = 0; k < 3; ++k)
  371.             {
  372.                 vertices[k] . normal[0] = n[0]; 
  373.                 vertices[k] . normal[1] = n[1]; 
  374.                 vertices[k] . normal[2] = n[2]; 
  375.                 vertices[k] . colorIndex = 0;
  376.             }
  377.  
  378.             /*Arrow edge*/
  379.             vertices[0] . position[0] = x1 - r[0] * headWidth;
  380.             vertices[0] . position[1] = y1 - r[1] * headWidth;
  381.             vertices[0] . position[2] = z1 - r[2] * headWidth;
  382.  
  383.             /*Arrow tip*/
  384.             vertices[1] . position[0] = x1 + vx;
  385.             vertices[1] . position[1] = y1 + vy;
  386.             vertices[1] . position[2] = z1 + vz;
  387.  
  388.             /*Arrow edge*/
  389.             vertices[2] . position[0] = x1 + r[0] * headWidth;
  390.             vertices[2] . position[1] = y1 + r[1] * headWidth;
  391.             vertices[2] . position[2] = z1 + r[2] * headWidth;
  392.  
  393.             AppendPolyToPicture(picture, 3, vertices);
  394.             }
  395.             else
  396.             {
  397.             Vertex vertices[7];
  398.  
  399.             /*Set up vertices*/
  400.             for (k = 0; k < 7; ++k)
  401.             {
  402.                 vertices[k] . normal[0] = n[0]; 
  403.                 vertices[k] . normal[1] = n[1]; 
  404.                 vertices[k] . normal[2] = n[2]; 
  405.                 vertices[k] . colorIndex = 0;
  406.             }
  407.  
  408.             /*Base corner*/
  409.             vertices[0] . position[0] = x1 - r[0] * shaftWidth;
  410.             vertices[0] . position[1] = y1 - r[1] * shaftWidth;
  411.             vertices[0] . position[2] = z1 - r[2] * shaftWidth;
  412.  
  413.             /*Arrow armpit*/
  414.             vertices[1] . position[0] = x1 + vx - headLength * a[0] - r[0] * shaftWidth;
  415.             vertices[1] . position[1] = y1 + vy - headLength * a[1] - r[1] * shaftWidth;
  416.             vertices[1] . position[2] = z1 + vz - headLength * a[2] - r[2] * shaftWidth;
  417.  
  418.             /*Arrow edge*/
  419.             vertices[2] . position[0] = x1 + vx - headLength * a[0] - r[0] * headWidth;
  420.             vertices[2] . position[1] = y1 + vy - headLength * a[1] - r[1] * headWidth;
  421.             vertices[2] . position[2] = z1 + vz - headLength * a[2] - r[2] * headWidth;
  422.  
  423.             /*Arrow tip*/
  424.             vertices[3] . position[0] = x1 + vx;
  425.             vertices[3] . position[1] = y1 + vy;
  426.             vertices[3] . position[2] = z1 + vz;
  427.  
  428.             /*Arrow edge*/
  429.             vertices[4] . position[0] = x1 + vx - headLength * a[0] + r[0] * headWidth;
  430.             vertices[4] . position[1] = y1 + vy - headLength * a[1] + r[1] * headWidth;
  431.             vertices[4] . position[2] = z1 + vz - headLength * a[2] + r[2] * headWidth;
  432.  
  433.             /*Arrow armpit*/
  434.             vertices[5] . position[0] = x1 + vx - headLength * a[0] + r[0] * shaftWidth;
  435.             vertices[5] . position[1] = y1 + vy - headLength * a[1] + r[1] * shaftWidth;
  436.             vertices[5] . position[2] = z1 + vz - headLength * a[2] + r[2] * shaftWidth;
  437.  
  438.             /*Base corner*/
  439.             vertices[6] . position[0] = x1 + r[0] * shaftWidth;
  440.             vertices[6] . position[1] = y1 + r[1] * shaftWidth;
  441.             vertices[6] . position[2] = z1 + r[2] * shaftWidth;
  442.  
  443.             AppendPolyToPicture(picture, 7, vertices);
  444.             }
  445.         }
  446.         break;
  447.         case AS_WIRE:
  448.         {
  449.             int k;
  450.             float r[3];        /*Radial unit vector*/
  451.             float n[3];        /*Normal unit vector*/
  452.             float a[3];        /*Axial unit vector*/
  453.             double length, nf;
  454.  
  455.             a[0] = vx;
  456.             a[1] = vy;
  457.             a[2] = vz;
  458.  
  459.             length = sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
  460.             if (length <= 0.0)
  461.             {
  462.             /*Zero length vector, do nothing*/
  463.             break;
  464.             }
  465.  
  466.             nf = 1.0 / length;
  467.             a[0] *= nf; a[1] *= nf; a[2] *= nf;
  468.  
  469.             /*See if it's nearly colinear with k*/
  470.             if (ABS(a[2]) > 0.8)
  471.             {
  472.             /*It is, so cross by j to get first r*/
  473.             r[0] = -a[2];
  474.             r[1] = 0.0;
  475.             r[2] = a[0];
  476.             }
  477.             else
  478.             {
  479.             /*It isn't, so cross by k to get first r*/
  480.             r[0] = -a[1];
  481.             r[1] = a[0];
  482.             r[2] = 0;
  483.             }
  484.  
  485.             NORMALIZE(r);
  486.  
  487.             /*Cross a with first radial unit to get orthogonal unit*/
  488.             CROSS(a, r, n);
  489.  
  490.             /*Fill in the vertices and draw*/
  491.  
  492.             if (headLength >= len)
  493.             {
  494.             /*There's no shaft*/
  495.             Vertex vertices[5];
  496.  
  497.             /*Set up vertices*/
  498.             for (k = 0; k < 5; ++k)
  499.             {
  500.                 vertices[k] . normal[0] = n[0]; 
  501.                 vertices[k] . normal[1] = n[1]; 
  502.                 vertices[k] . normal[2] = n[2]; 
  503.                 vertices[k] . colorIndex = 0;
  504.             }
  505.  
  506.             /*Base*/
  507.             vertices[0] . position[0] = x1;
  508.             vertices[0] . position[1] = y1;
  509.             vertices[0] . position[2] = z1;
  510.  
  511.             /*Arrow tip*/
  512.             vertices[1] . position[0] = x1 + vx;
  513.             vertices[1] . position[1] = y1 + vy;
  514.             vertices[1] . position[2] = z1 + vz;
  515.  
  516.             /*Arrow edge*/
  517.             vertices[2] . position[0] = x1 - r[0] * headWidth;
  518.             vertices[2] . position[1] = y1 - r[1] * headWidth;
  519.             vertices[2] . position[2] = z1 - r[2] * headWidth;
  520.  
  521.             /*Arrow edge*/
  522.             vertices[3] . position[0] = x1 + r[0] * headWidth;
  523.             vertices[3] . position[1] = y1 + r[1] * headWidth;
  524.             vertices[3] . position[2] = z1 + r[2] * headWidth;
  525.  
  526.             /*Arrow tip*/
  527.             vertices[4] . position[0] = x1 + vx;
  528.             vertices[4] . position[1] = y1 + vy;
  529.             vertices[4] . position[2] = z1 + vz;
  530.  
  531.             AppendPolylineToPicture(picture, 1, 0, 3, vertices);
  532.             AppendPolylineToPicture(picture, 1, 0, 2, &(vertices[3]));
  533.             }
  534.             else
  535.             {
  536.             Vertex vertices[5];
  537.  
  538.             /*Set up vertices*/
  539.             for (k = 0; k < 5; ++k)
  540.             {
  541.                 vertices[k] . normal[0] = n[0]; 
  542.                 vertices[k] . normal[1] = n[1]; 
  543.                 vertices[k] . normal[2] = n[2]; 
  544.                 vertices[k] . colorIndex = 0;
  545.             }
  546.  
  547.             /*Base*/
  548.             vertices[0] . position[0] = x1;
  549.             vertices[0] . position[1] = y1;
  550.             vertices[0] . position[2] = z1;
  551.  
  552.             /*Arrow tip*/
  553.             vertices[1] . position[0] = x1 + vx;
  554.             vertices[1] . position[1] = y1 + vy;
  555.             vertices[1] . position[2] = z1 + vz;
  556.  
  557.             /*Arrow edge*/
  558.             vertices[2] . position[0] = x1 + vx - headLength * a[0] - r[0] * headWidth;
  559.             vertices[2] . position[1] = y1 + vy - headLength * a[1] - r[1] * headWidth;
  560.             vertices[2] . position[2] = z1 + vz - headLength * a[2] - r[2] * headWidth;
  561.  
  562.             /*Arrow edge*/
  563.             vertices[3] . position[0] = x1 + vx - headLength * a[0] + r[0] * headWidth;
  564.             vertices[3] . position[1] = y1 + vy - headLength * a[1] + r[1] * headWidth;
  565.             vertices[3] . position[2] = z1 + vz - headLength * a[2] + r[2] * headWidth;
  566.  
  567.             /*Arrow tip*/
  568.             vertices[4] . position[0] = x1 + vx;
  569.             vertices[4] . position[1] = y1 + vy;
  570.             vertices[4] . position[2] = z1 + vz;
  571.  
  572.             AppendPolylineToPicture(picture, 1, 0, 3, vertices);
  573.             AppendPolylineToPicture(picture, 1, 0, 2, &(vertices[3]));
  574.             }
  575.         }
  576.         break;
  577.         case AS_SOLID:
  578.         if (headLength >= len)
  579.         {
  580.             /*There's no shaft*/
  581.             float end1[3], rad1, end2[3], rad2;
  582.  
  583.             end1[0] = x1;
  584.             end1[1] = y1;
  585.             end1[2] = z1;
  586.             rad1 = headWidth;
  587.             end2[0] = x1 + vx;
  588.             end2[1] = y1 + vy;
  589.             end2[2] = z1 + vz;
  590.             rad2 = 0.0;
  591.             ConvertFrustumOntoPicture(picture, end1, rad1, end2, rad2, nSubdivisions, curCapEnds);
  592.         }
  593.         else
  594.         {
  595.             /*There is a shaft*/
  596.             float end1[3], rad1, end2[3], rad2;
  597.  
  598.             end1[0] = x1;
  599.             end1[1] = y1;
  600.             end1[2] = z1;
  601.             rad1 = shaftWidth;
  602.             end2[0] = x1 + nx * (len - headLength);
  603.             end2[1] = y1 + ny * (len - headLength);
  604.             end2[2] = z1 + nz * (len - headLength);
  605.             rad2 = shaftWidth;
  606.             ConvertFrustumOntoPicture(picture, end1, rad1, end2, rad2, nSubdivisions, curCapEnds);
  607.             rad2 = headWidth;
  608.             end1[0] = x1 + vx;
  609.             end1[1] = y1 + vy;
  610.             end1[2] = z1 + vz;
  611.             rad1 = 0.0;
  612.             ConvertFrustumOntoPicture(picture, end1, rad1, end2, rad2, nSubdivisions, curCapEnds);
  613.         }
  614.         break;
  615.         }
  616.  
  617. nextOne:
  618.         /*Advance to next arrow*/
  619.         for (whichDim = 0; whichDim < nTraversalDims; ++whichDim)
  620.         {
  621.         if (traversalDims[whichDim] > 0)
  622.         {
  623.             if ((++indices[whichDim]) >= traversalDims[whichDim])
  624.             {
  625.             indices[whichDim] = 0;
  626.             }
  627.             else
  628.             {
  629.             break;
  630.             }
  631.         }
  632.         }
  633.     } while (whichDim < nTraversalDims); /*Break is based on advance*/
  634.     SAFEFREE(traversalDims);
  635.     SAFEFREE(indices);
  636.     }
  637.  
  638.     SetVar(visObject, SURFACE, picture);
  639.     SetVar(picture, REPOBJ, visObject);
  640.     return ObjTrue;
  641. }
  642.  
  643. static ObjPtr AddArrowsControls(arrows, panelContents)
  644. ObjPtr arrows, panelContents;
  645. /*Adds controls appropriate to an arrows object to panelContents*/
  646. {
  647.     ObjPtr titleBox, button, radio, var, corral, icon, name, arrowsField, mainDataset;
  648.     ObjPtr textBox, defaultIcon;
  649.     int width, left, top, bottom, right, mid;
  650.     int style;
  651.  
  652.     /*Put in the arrow corral at the top left*/
  653.     left = MAJORBORDER;
  654.     top = MAJORBORDER;
  655.     corral = NewIconCorral(NULLOBJ,
  656.                left, left + ONECORRALWIDTH,
  657.                CWINHEIGHT - MAJORBORDER - ONECORRALHEIGHT,
  658.                CWINHEIGHT - MAJORBORDER, 0);
  659.     SetVar(corral, SINGLECORRAL, ObjTrue);
  660.     SetVar(corral, TOPDOWN, ObjTrue);
  661.     SetVar(corral, NAME, NewString("Arrows Field"));
  662.     SetVar(corral, HELPSTRING,
  663.     NewString("This corral shows the dataset that is being used to make \
  664. the arrows display.  The locations, directions, and lengths of the arrows \
  665. are calculated using this field."));
  666.     PrefixList(panelContents, corral);
  667.     SetVar(corral, PARENT, panelContents);
  668.     SetVar(corral, REPOBJ, arrows);
  669.     SetMethod(corral, DROPINCONTENTS, DropInMainDatasetCorral);
  670.  
  671.     /*Create the arrows source text box*/
  672.     textBox = NewTextBox(left, left + ONECORRALWIDTH, 
  673.              CWINHEIGHT - MAJORBORDER - ONECORRALHEIGHT - TEXTBOXSEP - TEXTBOXHEIGHT,
  674.              CWINHEIGHT - MAJORBORDER - ONECORRALHEIGHT - TEXTBOXSEP,
  675.              0, "Arrows Field Text", "Arrows Field");
  676.     PrefixList(panelContents, textBox);
  677.     SetVar(textBox, PARENT, panelContents);
  678.     SetTextAlign(textBox, CENTERALIGN);
  679.  
  680.     /*Put in an icon that represents the field*/
  681.     arrowsField = GetObjectVar("AddArrowsControls", arrows, MAINDATASET);
  682.     if (!arrowsField) return ObjFalse;
  683.     while (mainDataset = GetVar(arrowsField, MAINDATASET))
  684.     {
  685.     arrowsField = mainDataset;
  686.     }
  687.  
  688.     name = GetStringVar("AddArrowsControls", arrowsField, NAME);
  689.     defaultIcon = GetVar(arrowsField, DEFAULTICON);
  690.     if (defaultIcon)
  691.     {
  692.     icon = NewObject(defaultIcon, 0);
  693.     SetVar(icon, NAME, name);
  694.     }
  695.     else
  696.     {
  697.     icon = NewIcon(0, 0, ICONQUESTION, GetString(name));
  698.     }
  699.     SetVar(icon, ICONLOC, NULLOBJ);
  700.     SetVar(icon, REPOBJ, arrowsField);
  701.     DropIconInCorral(corral, icon);
  702.  
  703.     top = CWINHEIGHT - MAJORBORDER - ONECORRALHEIGHT - TEXTBOXSEP - TEXTBOXHEIGHT - MINORBORDER;
  704.     left = MAJORBORDER;
  705.  
  706.     /*Create the arrow length factor text box*/
  707.     mid = top - EDITBOXHEIGHT / 2;
  708.     textBox = NewTextBox(left, left + ACNAMEWIDTH,
  709.              mid - TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  710.              mid + TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  711.              0, "Arrow Length Text", "Arrow Length:");
  712.     PrefixList(panelContents, textBox);
  713.     SetVar(textBox, PARENT, panelContents);
  714.  
  715.     var = GetRealVar("AddArrowControls", arrows, VECTORFACTOR);
  716.     if (!var)
  717.     {
  718.     return ObjFalse;
  719.     }
  720.  
  721.     textBox = NewTextBox(left + ACNAMEWIDTH + MINORBORDER,
  722.              left + ACNAMEWIDTH + MINORBORDER + ACTEXTWIDTH,
  723.              mid - EDITBOXHEIGHT / 2, mid + EDITBOXHEIGHT / 2,
  724.              EDITABLE + WITH_PIT + ONE_LINE, "Arrow Length Number", "");
  725.     SetVar(textBox, PARENT, panelContents);
  726.     PrefixList(panelContents, textBox);
  727.     SetTextAlign(textBox, RIGHTALIGN);
  728.     SetVar(textBox, HELPSTRING, NewString("This text box alters the length of \
  729. the arrows.  The number is the factor multiplied by the vector field to produce the \
  730. displacement to the tip of the arrow."));
  731.     AssocTextRealControlWithVar(textBox, arrows, VECTORFACTOR, minusInf, plusInf, TR_NE_TOP | TR_NE_BOTTOM);
  732.     top -= EDITBOXHEIGHT + MINORBORDER;
  733.  
  734.     /*Create the shaft width text box*/
  735.     mid = top - EDITBOXHEIGHT / 2;
  736.     textBox = NewTextBox(left, left + ACNAMEWIDTH,
  737.              mid - TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  738.              mid + TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  739.              0, "Shaft Radius Text", "Shaft Radius:");
  740.     PrefixList(panelContents, textBox);
  741.     SetVar(textBox, PARENT, panelContents);
  742.  
  743.     var = GetRealVar("AddArrowControls", arrows, SHAFTWIDTH);
  744.     if (!var)
  745.     {
  746.     return ObjFalse;
  747.     }
  748.  
  749.     textBox = NewTextBox(left + ACNAMEWIDTH + MINORBORDER,
  750.              left + ACNAMEWIDTH + MINORBORDER + ACTEXTWIDTH,
  751.              mid - EDITBOXHEIGHT / 2, mid + EDITBOXHEIGHT / 2,
  752.              EDITABLE + WITH_PIT + ONE_LINE, "Shaft Radius Number", "");
  753.     SetVar(textBox, PARENT, panelContents);
  754.     PrefixList(panelContents, textBox);
  755.     SetTextAlign(textBox, RIGHTALIGN);
  756.     SetVar(textBox, HELPSTRING, NewString("This text box controls the radius of \
  757. the arrow shaft.  The number is in field coordinates."));
  758.     AssocTextRealControlWithVar(textBox, arrows, SHAFTWIDTH, minusInf, plusInf, TR_NE_TOP | TR_NE_BOTTOM);
  759.     top -= EDITBOXHEIGHT + MINORBORDER;
  760.  
  761.     /*Create the head radius text box*/
  762.     mid = top - EDITBOXHEIGHT / 2;
  763.     textBox = NewTextBox(left, left + ACNAMEWIDTH,
  764.              mid - TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  765.              mid + TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  766.              0, "Head Radius Text", "Head Radius:");
  767.     PrefixList(panelContents, textBox);
  768.     SetVar(textBox, PARENT, panelContents);
  769.  
  770.     var = GetRealVar("AddArrowControls", arrows, HEADWIDTH);
  771.     if (!var)
  772.     {
  773.     return ObjFalse;
  774.     }
  775.  
  776.     textBox = NewTextBox(left + ACNAMEWIDTH + MINORBORDER,
  777.              left + ACNAMEWIDTH + MINORBORDER + ACTEXTWIDTH,
  778.              mid - EDITBOXHEIGHT / 2, mid + EDITBOXHEIGHT / 2,
  779.              EDITABLE + WITH_PIT + ONE_LINE, "Head Radius Number", "");
  780.     SetVar(textBox, PARENT, panelContents);
  781.     PrefixList(panelContents, textBox);
  782.     SetTextAlign(textBox, RIGHTALIGN);
  783.     SetVar(textBox, HELPSTRING, NewString("This text box controls the radius of \
  784. the arrowhead.  The number is in field coordinates.  To make the arrows look like \
  785. pencil shapes, make this number the same as the shaft radius."));
  786.     AssocTextRealControlWithVar(textBox, arrows, HEADWIDTH, minusInf, plusInf, TR_NE_TOP | TR_NE_BOTTOM);
  787.     top -= EDITBOXHEIGHT + MINORBORDER;
  788.  
  789.     /*Create the head length text box*/
  790.     mid = top - EDITBOXHEIGHT / 2;
  791.     textBox = NewTextBox(left, left + ACNAMEWIDTH,
  792.              mid - TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  793.              mid + TEXTBOXHEIGHT / 2 + EDITBOXDOWN,
  794.              0, "Head Length Text", "Head Length:");
  795.     PrefixList(panelContents, textBox);
  796.     SetVar(textBox, PARENT, panelContents);
  797.  
  798.     var = GetRealVar("AddArrowControls", arrows, HEADLENGTH);
  799.     if (!var)
  800.     {
  801.     return ObjFalse;
  802.     }
  803.  
  804.     textBox = NewTextBox(left + ACNAMEWIDTH + MINORBORDER,
  805.              left + ACNAMEWIDTH + MINORBORDER + ACTEXTWIDTH,
  806.              mid - EDITBOXHEIGHT / 2, mid + EDITBOXHEIGHT / 2,
  807.              EDITABLE + WITH_PIT + ONE_LINE, "Head Length Number", "");
  808.     SetVar(textBox, PARENT, panelContents);
  809.     PrefixList(panelContents, textBox);
  810.     SetTextAlign(textBox, RIGHTALIGN);
  811.     SetVar(textBox, HELPSTRING, NewString("This text box controls the length of \
  812. the arrowhead.  The number is in field coordinates.  To make the arrows look like \
  813. skinny needles, make this number infinity."));
  814.     AssocTextRealControlWithVar(textBox, arrows, HEADLENGTH, minusInf, plusInf, 0);
  815.     top -= EDITBOXHEIGHT + MINORBORDER;
  816.  
  817.     /*Make the arrows style radio buttons*/
  818.     titleBox = TemplateTitleBox(ArrowsTemplate, "Arrow Style");
  819.     PrefixList(panelContents, titleBox);
  820.     SetVar(titleBox, PARENT, panelContents);
  821.  
  822.     radio = NewRadioButtonGroup("Arrow Style Radio");
  823.     PrefixList(panelContents, radio);
  824.     SetVar(radio, PARENT, panelContents);
  825.  
  826.     button = TemplateRadioButton(ArrowsTemplate, "Line");
  827.     AddRadioButton(radio, button);
  828.     SetVar(button, HELPSTRING, NewString("When this button is on, the \
  829. arrows will be drawn as a single line.  This is the fastest way of drawing \
  830. arrows."));
  831.  
  832.     button = TemplateRadioButton(ArrowsTemplate, "Wire");
  833.     AddRadioButton(radio, button);
  834.     SetVar(button, HELPSTRING, NewString("When this button is on, the \
  835. arrows will be drawn in wire frame."));
  836.  
  837.     button = TemplateRadioButton(ArrowsTemplate, "Flat");
  838.     AddRadioButton(radio, button);
  839.     SetVar(button, HELPSTRING, NewString("When this button is on, the \
  840. arrows will be drawn as flat, shaded, 2-D arrows."));
  841.  
  842.     button = TemplateRadioButton(ArrowsTemplate, "Solid");
  843.     AddRadioButton(radio, button);
  844.     SetVar(button, HELPSTRING, NewString("When this button is on, the \
  845. arrows will be drawn as solid, shaded, cylindrical 3-D arrows.."));
  846.  
  847.     var = GetVar(arrows, STYLE);
  848.     if (!var)
  849.     {
  850.     SetVar(arrows, STYLE, NewInt(0));
  851.     }
  852.     AssocDirectControlWithVar(radio, arrows, STYLE);
  853.     SetVar(radio, HELPSTRING, NewString("These radio buttons control the \
  854. style of arrows display used.  Press a button to change the style."));
  855.  
  856.     return ObjTrue;
  857. }
  858.  
  859. void InitArrows()
  860. /*Initializes the arrows object*/
  861. {
  862.     ObjPtr icon;
  863.  
  864.     /*Class for an arrows object*/
  865.     arrowsClass = NewObject(visGeometryClass, 0);
  866.     AddToReferenceList(arrowsClass);
  867.     SetVar(arrowsClass, NAME, NewString("Arrows"));
  868.     SetMethod(arrowsClass, INITIALIZE, ArrowsInit);
  869.     SetVar(arrowsClass, DEFAULTICON, icon = NewObject(visIcon, 0));
  870.     SetVar(icon, WHICHICON, NewInt(ICONARROWS));
  871.     SetVar(icon, NAME, NewString("Arrows"));
  872.     SetVar(icon, HELPSTRING,
  873.     NewString("This icon represents an arrows object.  The arrows object \
  874. shows arrows at samples of a vector field with 2 or 3 components."));
  875.     DeclareIndirectDependency(arrowsClass, SURFACE, MAINDATASET, CHANGED);
  876.     DeclareIndirectDependency(arrowsClass, SURFACE, MAINDATASET);
  877.     DeclareDependency(arrowsClass, SURFACE, VECTORFACTOR);
  878.     DeclareDependency(arrowsClass, SURFACE, SHAFTWIDTH);
  879.     DeclareDependency(arrowsClass, SURFACE, HEADWIDTH);
  880.     DeclareDependency(arrowsClass, SURFACE, HEADLENGTH);
  881.     DeclareDependency(arrowsClass, SURFACE, STYLE);
  882.     SetMethod(arrowsClass, SURFACE, MakeArrowsSurface);
  883.     SetMethod(arrowsClass, PICCOLORED, MakeArrowsColored);
  884.     SetMethod(arrowsClass, SETMAINDATASET, SetArrowsMainDataset);
  885.     SetVar(arrowsClass, STYLE, NewInt(0));
  886.  
  887.     SetMethod(arrowsClass, ADDCONTROLS, AddArrowsControls);
  888.     icon = NewIcon(0, 0, ICONARROWS, "Arrows");
  889.     SetVar(arrowsClass, CONTROLICON, icon);
  890.  
  891.     DefineVisMapping(DS_HASFORM | DS_HASFIELD | DS_VECTOR, -1, 3, 3, arrowsClass);
  892.     DefineVisMapping(DS_HASFORM | DS_HASFIELD | DS_VECTOR, -1, 2, 3, arrowsClass);
  893.     DefineVisMapping(DS_HASFORM | DS_HASFIELD | DS_VECTOR, -1, 3, 2, arrowsClass);
  894.     DefineVisMapping(DS_HASFORM | DS_HASFIELD | DS_VECTOR, -1, 2, 2, arrowsClass);
  895. }
  896.  
  897. void KillArrows()
  898. /*Kills the arrows*/
  899. {
  900.     DeleteThing(arrowsClass);
  901. }
  902.